#include "public.h"

namespace idc
{
    char *deletelchr(char *str, const int cc)
    {
        if (str == nullptr)
            return nullptr;
        // 遍历字符串str，使得p指向第一个不是cc的字符
        char *p = str;
        while (*p == cc)
        {
            p++;
        }
        memmove(str, p, strlen(str) - (p - str) + 1); // 把结尾标志'\0’也拷贝
        return str;
    }

    string &deletelchr(string &str, const int cc)
    {
        size_t pos = str.find_first_not_of(cc); // pos：字符串str中第一个字符不为cc的位置
        if (pos != 0)
        {
            str.replace(0, pos, ""); // 把0-pos位置之间的字符串替换成空（字符串输出是从第一个不为0的的字符开始输出直到遇到第一个0,结束）
        }
        return str;
    }

    char *deleterchr(char *str, const int cc)
    {
        if (str == nullptr)
            return nullptr;
        // ++++jimi++++ ->  ++++jimi
        char *p = str;     // p指向字符串首地址
        char *p_is_cc = 0; // p_is_cc指向右边字符全是cc的第一个位置
        while (*p != 0)
        {
            if (*p == cc && p_is_cc == 0)
                p_is_cc = p; // 记下字符cc的第一个位置
            if (*p != cc)
                p_is_cc = 0; // 只要当前字符不是cc，p_is_cc清零
            p++;
        }
        // 直接把p_is_cc位置元素置为0即可
        if (p_is_cc != 0)
            *p_is_cc = '\0';
        return str;
    }

    string &deleterchr(string &str, const int cc)
    {
        size_t pos = str.find_last_not_of(cc); // 查找最后一个不为cc字符的位置
        if (pos != 0)
            str.erase(pos + 1); // 删除从pos往后的字符串
        return str;
    }

    char *deletelrchr(char *str, const int cc)
    {
        deletelchr(str, cc);
        deleterchr(str, cc);
        return str;
    }

    string &deletelrchr(string &str, const int cc)
    {
        deletelchr(str, cc);
        deleterchr(str, cc);
        return str;
    }

    char *toupper(char *str)
    {
        if (str == nullptr)
            return nullptr;
        char *p = str;
        while (*p != 0)
        {
            if ((*p >= 'a') && (*p <= 'z'))
            {
                *p -= 32;
            }
            p++;
        }
        return str;
    }

    string &toupper(string &str)
    {
        for (char &ch : str)
        {
            if (ch >= 'a' && ch <= 'z')
            {
                ch -= 32;
            }
        }
        return str;
    }

    char *tolower(char *str)
    {
        if (str == nullptr)
            return nullptr;
        char *p = str;
        while (*p != 0)
        {
            if (*p >= 'A' && *p <= 'Z')
            {
                *p += 32;
            }
            p++;
        }
        return str;
    }

    string &tolower(string &str)
    {
        for (char &ch : str)
        {
            if (ch >= 'A' && ch <= 'Z')
            {
                ch += 32;
            }
        }
        return str;
    }

    bool replacestr(char *str, const string &str1, const string &str2, const bool bloop)
    {
        if (str == nullptr)
        {
            return false;
        }
        // 通过调用string版本的replacestr函数完成c风格版本的replacestr
        string str_temp(str);
        replacestr(str_temp, str1, str2, bloop);
        str_temp.copy(str, str_temp.length()); // 把替换过的str_temp拷贝给str
        str[str_temp.length()] = '\0';         // string的copy函数不会给c风格字符串结尾加0
        return true;
    }

    bool replacestr(string &str, const string &str1, const string &str2, const bool bloop)
    {
        // 如果原字符串str或旧的内容str1为空，没有意义，不执行替换
        if (str.empty() || str1.empty())
            return false;
        // 如果bloop为true并且str2包含了str1的内容，直接返回，避免程序进入死循环导致内存溢出
        if (bloop == true && (str2.find(str1) != string::npos))
            return false;

        int pstart = 0; // 如果bloop == true， 下次执行替换的位置
        int ppos = 0;   // 本次需要替换的位置
        while (true)
        {
            if (bloop == true)
            {
                ppos = str.find(str1); // 每次都从头开始遍历替换
            }
            else
            {
                ppos = str.find(str1, pstart);
            }
            if (ppos == string::npos) // 没找到字串str1，直接退出，不进行替换
            {

                break;
            }
            str.replace(ppos, str1.length(), str2); // 执行替换
            if (bloop == false)
            {
                pstart = ppos + str2.length();
            }
        }
        return true;
    }

    char *picknumber(const string &src, char *dest, const bool bsigned, const bool bdot)
    {
        if (dest == nullptr)
        {
            return nullptr;
        }
        string tmp = picknumber(src, bsigned, bdot);
        tmp.copy(dest, tmp.length()); // copy tmp 给 dest
        dest[tmp.length()] = '\0';
        return dest;
    }

    string &picknumber(const string &src, string &dest, const bool bsigned, const bool bdot)
    {
        // 为了支持src和dest是同一变量的情况，定义tmp临时变量
        string tmp;
        for (const char &ch : src)
        {
            // 判断是否提取符号'+' '-'
            if ((bsigned == true) && (ch == '+' || ch == '-'))
            {
                tmp.append(1, ch);
                continue;
            }
            // 判断是否提取 '.'
            if ((bdot == true) && (ch == '.'))
            {
                tmp.append(1, ch);
                continue;
            }
            // 提取数字
            if (isdigit(ch))
            {
                tmp.append(1, ch);
            }
        }
        dest = tmp;
        return dest;
    }

    string picknumber(const string &src, const bool bsigned, const bool bdot)
    {
        string dest;
        picknumber(src, dest, bsigned, bdot);
        return dest;
    }

    bool matchstr(const string &str, const string &rules)
    {
        // 如果匹配规则表达式的内容是空的，返回false。
        if (rules.length() == 0)
            return false;

        // 如果如果匹配规则表达式的内容是"*"，直接返回true。
        if (rules == "*")
            return true;

        int ii, jj;
        int pos1, pos2;
        Ccmdstr cmdstr, cmdsubstr;

        string filename = str;
        string matchstr = rules;

        // 把字符串都转换成大写后再来比较
        toupper(filename);
        toupper(matchstr);

        cmdstr.spilit_to_cmdstr(matchstr, ",");

        for (ii = 0; ii < cmdstr.size(); ii++)
        {
            // 如果为空，就一定要跳过，否则就会被匹配上。
            if (cmdstr[ii].empty() == true)
                continue;

            pos1 = pos2 = 0;
            cmdsubstr.spilit_to_cmdstr(cmdstr[ii], "*");

            for (jj = 0; jj < cmdsubstr.size(); jj++)
            {
                // 如果是文件名的首部
                if (jj == 0)
                    if (filename.substr(0, cmdsubstr[jj].length()) != cmdsubstr[jj])
                        break;

                // 如果是文件名的尾部
                if (jj == cmdsubstr.size() - 1)
                    if (filename.find(cmdsubstr[jj], filename.length() - cmdsubstr[jj].length()) == string::npos)
                        break;

                pos2 = filename.find(cmdsubstr[jj], pos1);

                if (pos2 == string::npos)
                    break;

                pos1 = pos2 + cmdsubstr[jj].length();
            }

            if (jj == cmdsubstr.size())
                return true;
        }

        return false;
    }

    Ccmdstr::Ccmdstr(const string &buffer, const string &seqstr, const bool bdelspace)
    {
        spilit_to_cmdstr(buffer, seqstr, bdelspace);
    }

    void Ccmdstr::spilit_to_cmdstr(const string &buffer, const string &seqstr, const bool bdelspace)
    {
        m_cmdstr.clear();  // 清空vector<string>容器
        int start_pos = 0; // 每次从buffer中查找分隔符的起始位置
        int split_pos = 0; // 从start_pos开始，查找下一个分隔符的位置
        string substr;

        // aaa,bbb,ccc,ddd
        while ((split_pos = buffer.find(seqstr, start_pos)) != string::npos)
        {
            substr = buffer.substr(start_pos, split_pos - start_pos); // 截取字串
            if (bdelspace == true)
            {
                deletelrchr(substr); // 去除字串的左右两边空格符, deletelrchr第二个参数缺省= ' '
            }
            m_cmdstr.push_back(std::move(substr)); // 把子串放入m_cmdstr容器中，调用string类的移动构造函数。
            start_pos = split_pos + seqstr.length();
        }

        // 处理最后一个字段（最后一个分隔符之后的内容)
        substr = buffer.substr(start_pos);
        if (bdelspace == true)
        {
            deletelrchr(substr);
        }
        m_cmdstr.push_back(std::move(substr));
        return;
    }

    bool Ccmdstr::get_value(const int i, string &value, const int len) const // c++风格
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }

        // 如果len比实际长度小，就只截取len长度的内容；如果len>=实际长度，那就按照实际长度来截取内容
        int value_len = m_cmdstr[i].length();
        if ((len > 0) && (len < value_len))
        {
            value_len = len;
        }
        value = m_cmdstr[i].substr(0, value_len);
        return true;
    }

    bool Ccmdstr::get_value(const int i, char *value, const int len) const
    {
        if ((i >= m_cmdstr.size()) || (value == nullptr))
        {
            return false;
        }
        if (len > 0)
        {
            memset(value, 0, len + 1); // 调用者必须保证value的空间足够，否则这里会内存溢出
        }
        // 如果len长度为0或者len长度比实际长度大，那就按照实际长度来拷贝
        if ((m_cmdstr[i].length() <= len) || (len == 0))
        {
            m_cmdstr[i].copy(value, m_cmdstr[i].length());
            value[m_cmdstr[i].length()] = '\0';
        }
        else
        {
            m_cmdstr[i].copy(value, len);
            value[len] = 0;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, int &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }

        try
        {
            value = stoi(picknumber(m_cmdstr[i], true)); // stoi有异常，需要处理异常
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, unsigned int &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        try
        {
            value = stoi(picknumber(m_cmdstr[i])); // picknumber第二个参数默认false，不提取正负号
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, long &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        try
        {
            value = stol(picknumber(m_cmdstr[i], true)); // stol有异常，需要处理异常。
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, unsigned long &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        try
        {
            value = stol(picknumber(m_cmdstr[i])); // stoul有异常，需要处理异常。不提取符号 + -
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, double &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        try
        {
            value = stod(picknumber(m_cmdstr[i], true, true)); // stod有异常，需要处理异常。提取符号和小数点。
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, float &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        try
        {
            value = stof(picknumber(m_cmdstr[i], true, true)); // stod有异常，需要处理异常。提取符号和小数点。
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool Ccmdstr::get_value(const int i, bool &value) const
    {
        if (i >= m_cmdstr.size())
        {
            return false;
        }
        // 没有stob的判断函数，通过统一转换成大写或者小写来判断
        // string tmp = m_cmdstr[i];
        // toupper(tmp);
        string tmp = toupper(const_cast<string &>(m_cmdstr[i]));

        if (tmp == "TRUE")
        {
            value = true;
        }
        else
        {
            value = false;
        }
        return true;
    }

    Ccmdstr::~Ccmdstr()
    {
        m_cmdstr.clear();
    }

    ostream &operator<<(ostream &out, const Ccmdstr &cc)
    {
        for (int i = 0; i < cc.size(); i++)
        {
            out << "[" << i << "]=" << cc[i] << endl;
        }
        return out;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, string &value, const int len)
    {
        string start_label = "<" + fieldname + ">";  // 数据项开始标签
        string end_label = "</" + fieldname + ">";   // 数据项结束标签
        int start_pos = xmlbuffer.find(start_label); // 开始标签位置
        if (start_pos == string::npos)
        {
            return false;
        }
        int end_pos = xmlbuffer.find(end_label); // 结束标签位置
        if (end_pos == string::npos)
        {
            return false;
        }

        int value_len = end_pos - start_pos - start_label.length(); // 字段长度
        // 如果len小于实际字段长度，那就截取ilen长度的字段内容；否则直接取实际字段长度
        if ((len > 0) && (len < value_len))
        {
            value_len = len;
        }
        value = xmlbuffer.substr(start_pos + start_label.length(), value_len);
        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, char *value, const int len)
    {
        if (value == nullptr)
        {
            return false;
        }
        if (len > 0)
        {
            memset(value, 0, len + 1); // 调用正必须保证value的空间足够，否者这里会内存溢出
        }
        string str;
        getxmlbuffer(xmlbuffer, fieldname, str); // 取得字段的实际长度，存放在str中

        // 如果len小于实际长度，那就截取len长度的字段内容；否则直接截取实际字段长度
        if ((len > 0) && (len < str.length()))
        {
            str.copy(value, len); // 从str中截取len长度的字符串给value
            value[len] = '\0';
        }
        else
        {
            // len太大，截取实际字段长度
            str.copy(value, str.length());
            value[str.length()] = '\0';
        }

        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, bool &value)
    {
        string str;
        int ret = getxmlbuffer(xmlbuffer, fieldname, str); // 取字段的实际字符串,存放在str
        if (ret == false)
        {
            return false;
        }
        if (str == "TRUE")
        {
            value = true;
        }
        else
        {
            value = false;
        }
        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, int &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str) == false)) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stoi(picknumber(str, true)); // stoi有异常，需要处理异常
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }
    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, unsigned int &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str)) == false) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stoi(picknumber(str)); // stoi有异常，需要处理异常。不提取符号 + -
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }
    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, long &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str)) == false) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stol(picknumber(str, true)); // stoi有异常，需要处理异常。不提取符号 + -
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, unsigned long &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str)) == false) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stol(picknumber(str)); // stoi有异常，需要处理异常。不提取符号 + -
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, double &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str)) == false) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stod(picknumber(str, true, true)); // stod有异常，需要处理异常。提取符号和小数点。
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    bool getxmlbuffer(const string &xmlbuffer, const string &fieldname, float &value)
    {
        string str;
        if ((getxmlbuffer(xmlbuffer, fieldname, str)) == false) // 取字段的实际字符串,存放在str
        {
            return false;
        }
        try
        {
            value = stof(picknumber(str, true, true)); // stod有异常，需要处理异常。提取符号和小数点。
        }
        catch (const std::exception &e)
        {
            return false;
        }
        return true;
    }

    string &timetostr(const time_t ttime, string &strtime, const string &fmt)
    {
        struct tm st_tm;                      // 声明一个tm类型是时间结构体
        localtime_r(&ttime, &st_tm);          // localtime_r线程安全，localtime非线程安全
        st_tm.tm_year = st_tm.tm_year + 1900; // 年份要加上1900
        st_tm.tm_mon++;                       // 获得是时间是从0开始的，所以实际要加1

        // 缺省是时间格式
        if ((fmt == "") || (fmt == "yyyy-mm-dd hh24:mi:ss"))
        {
            strtime = sformat("%04u-%02u-%02u %02u:%02u:%02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday,
                              st_tm.tm_hour, st_tm.tm_min, st_tm.tm_sec);
            return strtime;
        }

        if (fmt == "yyyy-mm-dd hh24:mi")
        {
            strtime = sformat("%04u-%02u-%02u %02u:%02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday,
                              st_tm.tm_hour, st_tm.tm_min);
            return strtime;
        }

        if (fmt == "yyyy-mm-dd hh24")
        {
            strtime = sformat("%04u-%02u-%02u %02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday, st_tm.tm_hour);
        }

        if (fmt == "yyyy-mm-dd")
        {
            strtime = sformat("%04u-%02u-%02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday);
            return strtime;
        }

        if (fmt == "yyyy-mm")
        {
            strtime = sformat("%04u-%02u", st_tm.tm_year, st_tm.tm_mon);
            return strtime;
        }

        if (fmt == "yyyymmddhh24miss")
        {
            strtime = sformat("%04u%02u%02u%02u%02u%02u", st_tm.tm_yday, st_tm.tm_mon, st_tm.tm_mday,
                              st_tm.tm_hour, st_tm.tm_min, st_tm.tm_sec);
            return strtime;
        }

        if (fmt == "yyyymmddhh24mi")
        {
            strtime = sformat("%04u%02u%02u%02%02u", st_tm.tm_yday, st_tm.tm_mon, st_tm.tm_mday,
                              st_tm.tm_hour, st_tm.tm_min);
            return strtime;
        }

        if (fmt == "yyyymmddhh24")
        {
            strtime = sformat("%04u%02u%02u%02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday, st_tm.tm_hour);
            return strtime;
        }

        if (fmt == "yyyymmdd")
        {
            strtime = sformat("%04u%02u%02u", st_tm.tm_year, st_tm.tm_mon, st_tm.tm_mday);
            return strtime;
        }

        if (fmt == "hh24miss")
        {
            strtime = sformat("%02u%02u%02u", st_tm.tm_hour, st_tm.tm_min, st_tm.tm_sec);
            return strtime;
        }

        if (fmt == "hh24mi")
        {
            strtime = sformat("%02u%02u", st_tm.tm_hour, st_tm.tm_min);
            return strtime;
        }

        if (fmt == "hh24")
        {
            strtime = sformat("%02u", st_tm.tm_hour);
            return strtime;
        }

        if (fmt == "mi")
        {
            strtime = sformat("%02u", st_tm.tm_min);
            return strtime;
        }

        return strtime;
    }

    char *timetostr(const time_t ttime, char *strtime, const string &fmt)
    {
        if (strtime == nullptr)
        {
            return nullptr;
        }
        string str;
        timetostr(ttime, str, fmt);
        str.copy(strtime, str.length());
        strtime[str.length()] = '\0';
        return strtime;
    }

    // 为了避免重载的岐义，增加timetostr1()函数。
    string timetostr1(const time_t ttime, const string &fmt)
    {
        string str;
        timetostr(ttime, str, fmt);
        return str;
    }

    string &ltime(string &strtime, const string &fmt, const int timetvl)
    {
        time_t timer;                   // long类型的时间参数
        time(&timer);                   // 获取系统当前时间
        timer += timetvl;               // 加上偏移量
        timetostr(timer, strtime, fmt); // 把long类型的时间参数按照fmt格式转换成字符串
        return strtime;
    }

    char *ltime(char *strtime, const string &fmt, const int timetvl)
    {
        if (strtime == nullptr)
        {
            return nullptr;
        }
        time_t timer;
        time(&timer);
        timer += timetvl;
        timetostr(timer, strtime, fmt);
        return strtime;
    }

    // 为了避免重载的岐义，增加ltime1()函数。
    string ltime1(const string &fmt, const int timetvl)
    {
        string strtime;
        ltime(strtime, fmt, timetvl); // 直接调用string& ltime(string &strtime,const string &fmt="",const int timetvl=0);
        return strtime;
    }

    time_t strtotime(const string &strtime)
    {
        string str_tmp;                             // 临时字符串
        string yyyy, mm, dd, hh, mi, ss;            // 年月日时分秒 字符串
        picknumber(strtime, str_tmp, false, false); // 只提取数字，不提取其他+ - .等字符
        // 2021-12-05 08:30:45
        // 2021/12/05 08:30:45
        // 20211205083045
        if (str_tmp.length() != 14)
        {
            return -1; // 如果时间格式不是yyyymmddhh24miss，说明时间格式不正确
        }
        // 提取每个部分数据
        yyyy = str_tmp.substr(0, 4);
        mm = str_tmp.substr(4, 2);
        dd = str_tmp.substr(6, 2);
        hh = str_tmp.substr(8, 2);
        mi = str_tmp.substr(10, 2);
        ss = str_tmp.substr(12, 2);

        struct tm st_tm; // 声明tm结构体
        // 给结构体每个成员赋值，需要处理异常
        try
        {
            st_tm.tm_year = stoi(yyyy) - 1900;
            st_tm.tm_mon = stoi(mm) - 1;
            st_tm.tm_mday = stoi(dd);
            st_tm.tm_hour = stoi(hh);
            st_tm.tm_min = stoi(mi);
            st_tm.tm_sec = stoi(ss);
            st_tm.tm_isdst = 0;
        }
        catch (const std::exception &e)
        {
            return -1;
        }

        return mktime(&st_tm); // 将tm类型的转换成time_t类型是时间，返回
    }

    bool addtime(const string &in_stime, string &out_stime, const int timetvl, const string &fmt)
    {
        time_t timer;
        // 把字符串表示的时间转换为整数表示的时间，方便运算
        if ((timer = strtotime(in_stime)) == -1)
        {
            out_stime = "";
            return false;
        }
        timer += timetvl;
        timetostr(timer, out_stime, fmt);
        return true;
    }

    bool addtime(const string &in_stime, char *out_stime, const int timetvl, const string &fmt)
    {
        if (out_stime == nullptr)
        {
            return false;
        }
        time_t timer;
        if ((timer = strtotime(in_stime)) == -1)
        {
            strcpy(out_stime, "");
            return false;
        }
        timer += timetvl;
        timetostr(timer, out_stime, fmt);
        return true;
    }

    Ctimer::Ctimer()
    {
        start();
    }

    void Ctimer::start()
    {
        memset(&m_start, 0, sizeof(struct timeval));
        memset(&m_end, 0, sizeof(struct timeval));
        gettimeofday(&m_start, 0); // 获取当前时间，精确到微秒
    }

    double Ctimer::elapsed()
    {
        gettimeofday(&m_end, 0); // 获取当前时间作为计时结束的时间，精确到微秒。
        string str;
        str = sformat("%ld.%06ld", m_start.tv_sec, m_start.tv_usec);
        double d_start = stod(str); // double类型的start时间

        str = sformat("%ld.%.06ld", m_end.tv_sec, m_end.tv_usec);
        double d_end = stod(str);

        start(); // 重新开始计时
        return d_end - d_start;
    }

    // namespace idc结束位置
}
